<?php

abstract class Storage_Adapter
{

	protected $_id = NULL;

	/**
	 * @var string
	 */
	protected $_baseUrl = '';

	/**
	 * @var string
	 */
	protected $_basePath = '';

	abstract function get($relative_path, $local_file, $force = TRUE);

	abstract function put($relative_path, $local_file, $force = TRUE);

	abstract function delete($relative_path, $force = FALSE);

	abstract function getContents($relative_path, $force = TRUE);

	abstract function putContents($relative_path, $data, $force = TRUE);

	function mapUrl($path)
	{
		return $this -> _baseUrl . $path;
	}

	function mapPath($path)
	{
		return $this -> _basePath . $path;
	}

	/**
	 * generate a path
	 * @return string
	 */
	static function generatePath($params)
	{
		static $algorithm = null;

		if (null == $algorithm)
		{
			$adapter = 'simple';
			require_once 'storage/pathtype/' . $adapter . '.php';
			$class_name = 'Storage_Pathtype_' . ucfirst($adapter);
			$algorithm = new $class_name;
		}

		return $algorithm -> generate($params);
	}

	static function getFileInfo($file)
	{
		if (is_string($file))
		{
			$info = array(
				'tmp_name' => $file,
				'name' => basename($file),
				'type' => 'unknown/unknown', // @todo
				'size' => filesize($file)
			);
			if (function_exists('getimagesize') && ($imageinfo = getimagesize($file)))
			{
				$info['type'] = $imageinfo['mime'];
			}
		}
		else
		if (is_array($file))
		{
			$info = $file;
		}
		else
		{
			throw new Agilet_Exception('Unknown file type specified');
		}

		// Check to make sure file exists and not security problem
		if (!@is_readable($info['tmp_name']))
		{
			throw new Agilet_Exception('File does not exist!');
		}

		// Do some other stuff
		$mime_parts = explode('/', $info['type'], 2);
		$info['mime_major'] = $mime_parts[0];
		$info['mime_minor'] = $mime_parts[1];
		$info['hash'] = md5_file($info['tmp_name']);
		$info['extension'] = ltrim(strrchr($info['name'], '.'), '.');
		unset($info['type']);

		return $info;
	}

	static function _makeLocalDir($path, $mode = 0777)
	{
		// Change umask
		if (function_exists('umask'))
		{
			$oldUmask = umask();
			umask(0);
		}

		// Change perms
		$code = 0;
		if (is_dir($path))
		{
			@chmod($path, $mode);
		}
		else
		if (!@mkdir($path, $mode, true))
		{
			$code = 1;
		}

		// Revert umask
		if (function_exists('umask'))
		{
			umask($oldUmask);
		}

		// Respond
		if (1 == $code)
		{
			throw new Agilet_Exception('Could not make dir "{path}"', array('{path}' => $path));
		}
	}

	static function _moveLocalFile($from, $to)
	{
		// Change umask
		if (function_exists('umask'))
		{
			$oldUmask = umask();
			umask(0);
		}

		// Move
		$code = 0;
		if (!is_file($from))
		{
			$code = 1;
		}
		else
		if (!@rename($from, $to))
		{
			@mkdir(dirname($to), 0777, true);
			if (!@rename($from, $to))
			{
				$code = 1;
			}
		}

		// Revert umask
		if (function_exists('umask'))
		{
			umask($oldUmask);
		}

		if (1 == $code)
		{
			throw new Agilet_Exception('Could not move file "{from}" => "{to}"', array(
				'{from}' => $from,
				'{to}' => $to
			));
		}
	}

	static function _deleteLocalFile($file)
	{
		// Delete
		$code = 0;
		if (is_file($file))
		{
			if (!@unlink($file))
			{
				@chmod($file, 0777);
				if (!@unlink($file))
				{
					$code = 1;
				}
			}
		}

		if (1 == $code)
		{
			throw new Agilet_Exception('Could not delete file "{file}"', array('{file}' => $file));
		}
	}

	static function _copyLocalFile($from, $to)
	{
		// Change umask
		if (function_exists('umask'))
		{
			$oldUmask = umask();
			umask(0);
		}

		// Copy
		$code = 0;
		if (!is_file($from))
		{
			$code = 1;
		}
		else
		if (!@copy($from, $to))
		{
			@mkdir(dirname($to), 0777, true);
			@chmod(dirname($to), 0777);
			if (!@copy($from, $to))
			{
				$code = 1;
			}
		}

		// Revert umask
		if (function_exists('umask'))
		{
			umask($oldUmask);
		}

		if (1 == $code)
		{
			throw new Agilet_Exception('Could not to copy file "{from}" => "{to}"', array(
				'{from}' => $from,
				'{to}' => $to
			));
		}
	}

	static function _writeLocalFile($file, $data)
	{
		// Change umask
		if (function_exists('umask'))
		{
			$oldUmask = umask();
			umask(0);
		}

		// Write
		$code = 0;
		if (!@file_put_contents($file, $data))
		{
			if (is_file($file))
			{
				@chmod($file, 0666);
			}
			else
			if (is_dir(dirname($file)))
			{
				@chmod(dirname($file), 0777);
			}
			else
			{
				@mkdir(dirname($file), 0777, true);
			}

			if (!@file_put_contents($file, $data))
			{
				$code = 1;
			}
		}

		// Revert umask
		if (function_exists('umask'))
		{
			umask($oldUmask);
		}

		if (1 == $code)
		{
			throw new Agilet_Exception(sprintf('Unable to write to file "{file}"', array('{file}' => $file)));
		}
	}

	static function _readLocalFile($local_file)
	{
		$content = NULL;
		if ($content = !@file_get_contents($local_file))
		{
			throw new Agilet_Exception('Unable to read file "{file}"', array('{file}' => $local_file));
		}
		return $content;
	}

}
